/* 
 *  Copyright (C) 2006 James Young
 * `gurumind(a)gmail.com
 * 
 */

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.IO;
using System.Configuration;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Soap;
//using System.Runtime.Serialization.Formatters.Binary;

namespace IPDEditor
{
    public partial class mainForm : Form
    {
        Dictionary<string, IPDUIFile> _openedFiles;
        string _currentFileName;
        string _appName = Properties.Settings.Default.appName;
        Editors _editors;

        public mainForm()
        {
            InitializeComponent();
        }

        private void mainForm_Load(object sender, EventArgs e)
        {
            _openedFiles = new Dictionary<string, IPDUIFile>();
#if DEBUG
            //LoadFile(@"..\..\..\tests\test.ipd");
            //LoadFile(@"..\..\..\tests\AutoText-test.ipd");
#endif
            lv.FullRowSelect = true;
            this.Text = _appName;
            status1.Text = "The berry that not so black.";  
          
            ////other init
            //_confFile = Directory.GetParent(Environment.CommandLine.Replace("\"", "")) + "\\Editors.format";
            //_editors = new Editors();
            //if (File.Exists(_confFile))
            //{
            //    Stream stream = File.Open(_confFile, FileMode.Open);
            //    SoapFormatter formatter = new SoapFormatter();
            //    _editors = (Editors)formatter.Deserialize(stream);
            //    stream.Close();
            //}
            
            this.Icon = IPDEditor.Properties.Resources.Main2;
        }

        private void mainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            //Stream stream = File.Open(_confFile, FileMode.Create);
            //SoapFormatter formatter = new SoapFormatter();
            //formatter.Serialize(stream, _editors);
            //stream.Close();
        }

        private string CurrentFileName
        {
            set
            {
                _currentFileName = value;
                if (_currentFileName != null)
                    this.Text = _currentFileName + " - " + _appName;
                else
                    this.Text = _appName;
            }
            get
            {
                return _currentFileName;
            }
        }

        private void ClearLV()
        {
            //foreach (ListViewItem lvi in lv.Items)
            //{
            //    if (lvi.Tag is IPDField)
            //    {
            //        IPDField fld = lvi.Tag as IPDField;
            //        fld.lvi = null;
            //    }
            //    lvi.Tag = null;
            //    lvi.Remove();
            //}
        }

        private void lv_Click(object sender, EventArgs e)
        {
            if (lv.SelectedItems.Count > 0 && lv.SelectedItems[0].Tag is IPDUIField)
            {
                IPDUIField uiField = (IPDUIField)lv.SelectedItems[0].Tag;
                ViewRec(uiField.field);
            }
            else if (lv.SelectedItems.Count > 0 && lv.SelectedItems[0].Tag is IPDVisualRecord)
            {
                IPDVisualRecord rec = (IPDVisualRecord)lv.SelectedItems[0].Tag;
                rec.CreateVisualView(tabVisual);
                ViewDatabase(rec.record);
            }
        }
        
        private void lv_DoubleClick(object sender, EventArgs e)
        {
            //if (lv.SelectedItems.Count > 0 && lv.SelectedItems[0].Tag is IPDDatabase)
            //{ 
            //    IPDDatabase db = (IPDDatabase)lv.SelectedItems[0].Tag;
            //    LoadFieldsIntoListView(db);
            //}
        }

        private void tv_AfterSelect(object sender, TreeViewEventArgs e)
        {
            //fill list view with data
            IPDUIFile uiFile;
            if (e.Node.Tag is IPDUIFile)
            {
                uiFile = (IPDUIFile)e.Node.Tag;
                uiFile.CreateListView(lv);                
            }
            else if (e.Node.Tag is IPDUIName)
            {
                IPDUIName uiName = (IPDUIName)e.Node.Tag;
                uiName.CreateListView(lv);
                uiFile = (IPDUIFile)e.Node.Parent.Tag;
            }
            else if (e.Node.Tag is IPDVisualRecord)
            {
                IPDVisualRecord rec = (IPDVisualRecord)e.Node.Tag;
                rec.CreateListView(lv);
                rec.CreateVisualView(tabVisual);
                ViewDatabase(rec.record);

                uiFile = (IPDUIFile)e.Node.Parent.Parent.Tag;
            }
            else if (e.Node.Tag is IPDUIField)
            {
                IPDUIField ufld = (IPDUIField)e.Node.Tag;
                ufld.CreateListView(lv);
                ufld.CreateVisualView(tabVisual);
                ViewRec(ufld.field);

                if(e.Node.Parent.Parent.Parent.Tag is IPDUIFile)
                    uiFile = (IPDUIFile)e.Node.Parent.Parent.Parent.Tag;
                else
                    uiFile = (IPDUIFile)e.Node.Parent.Parent.Parent.Parent.Tag;
            }
            else
            {
                MessageBox.Show("Add code here!");
                uiFile = null;
                return;
            }
            CurrentFileName = uiFile.ipdFile.FileName;            
        }

        private void ViewRec(IPDField rec)
        {
            if (rec == null || rec.data == null)
            {
                rt1.Text = null;
                return;
            }
            
            rt1.Text = EncUtil.Bin2RichFormat(rec.data, rec.offset);
        }

        private void ViewDatabase(IPDDatabase db)
        {
            if (db == null)
            {
                rt1.Text = null;
                return;
            }

            //assemble all the data of a database
            MemoryStream ms = new MemoryStream();
            BinaryWriter bw = new BinaryWriter(ms);
            db.Write(bw, !db.IsUnicode);
            byte [] buff = new byte[ms.Length];
            ms.Seek(0L, SeekOrigin.Begin);
            ms.Read(buff, 0, (int)ms.Length);
            rt1.Text = EncUtil.Bin2RichFormat(buff, db.offset);
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (DialogResult.OK == ofd.ShowDialog(this))
            {
                if (!_openedFiles.ContainsKey(ofd.FileName))
                    LoadFile(ofd.FileName);
                else
                    MessageBox.Show("File already opened!");
            }
        }

        private void LoadFile(string fileName)
        {
#if !DEBUG
            try
            {
#endif          
                IPDFile file = new IPDFile(fileName);
                file.Open();
                
                IPDUIFile uiFile = new IPDUIFile(file);

                //tv.Nodes.Clear();
                //ClearLV();
                tv.Nodes.Add(uiFile.CreateTreeNode());

                this.Text = fileName + " - " + _appName;

                _openedFiles.Add(fileName, uiFile);
#if !DEBUG
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                this.Text = _appName;
            }
#endif
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            new AboutBox1().ShowDialog(this);
        }

        private void lv_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lv.SelectedItems.Count >= 1)
            {
                if (lv.SelectedItems[0].Tag is IPDField)
                {
                    IPDField rec = (IPDField)lv.SelectedItems[0].Tag;
                    ViewRec(rec);
                    //IPDDatabase db = (IPDDatabase)_file.ipdDbs[tv.SelectedNode.Index];
                    //IPDField rec = (IPDField)db.alFld[lv.SelectedItems[0].Index];

                    //ViewRec(rec);
                }
                else
                    ViewRec(null);
            }
        }

        private void saveasToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if(DialogResult.OK == sfd.ShowDialog(this))
            {
                if (!_openedFiles.ContainsKey(sfd.FileName))
                {
                    IPDUIFile uiFile = _openedFiles[CurrentFileName];
                    uiFile.ipdFile.SaveAs(sfd.FileName);
                    //update the opened file list
                    _openedFiles.Remove(CurrentFileName);
                    _openedFiles.Add(uiFile.ipdFile.FileName, uiFile);
                    CurrentFileName = uiFile.ipdFile.FileName;

                    //change root node either
                    uiFile.Update();
                }
                else
                {
                    MessageBox.Show("The file you try to overwrite has already opened for editing. I'll do nothing.");
                }
            }
        }



        private void guessDataToolStripMenuItem_Click(object sender, EventArgs e)
        {
#if !DEBUG
            MessageBox.Show("This function is only for debug version.");
            return;
#else
            if (lv.SelectedItems.Count <= 0)
                return;

            ListViewItem lvi = lv.SelectedItems[0];
            if (lvi.Tag is IPDField)
            {
                IPDField fld = lvi.Tag as IPDField;
                IPDDocument doc = fld.Parent.Parent.Parent;

                //FileStream fs = File.OpenRead(doc.fileObject.FileName);
                //fs.Seek(fld.offset + 1, SeekOrigin.Begin);
                //byte[] buff = new byte[fld.len * 2];
                //fs.Read(buff, 0, fld.len * 2);
                //fs.Close();
                //buff[fld.len] = (byte)0;
                byte[] buff = new byte[fld.len];
                for (int i = 1; i < fld.len; i++)
                    buff[i - 1] = fld.data[i];

                FileStream fso = new FileStream("TMP.TMP", FileMode.OpenOrCreate);
                fso.SetLength(0);
                fso.Flush();
                EncodingInfo[] encinfo = Encoding.GetEncodings();

                for (int i = 0; i < encinfo.Length; i++)
                {
                    string s = encinfo[i].GetEncoding().GetString(buff);
                    byte[] b = encinfo[i].GetEncoding().GetBytes(s);
                    fso.Write(b, 0, b.Length);

                    byte[] c = Encoding.ASCII.GetBytes(encinfo[i].DisplayName);
                    fso.Write(c, 0, c.Length);
                    //for (int j = 0; j < encinfo.Length; j++)
                    //{
                    //    byte[] buffc = Encoding.Convert(encinfo[i].GetEncoding(), encinfo[j].GetEncoding(), buff);
                    //    fso.Write(buffc, 0, buffc.Length);
                    //}
                }

                fso.Close();

            }
#endif
        }

        private void closeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (TreeNode tn in tv.Nodes)
            {
                IPDUIFile uifile = tn.Tag as IPDUIFile;
                if (uifile.ipdFile.FileName == CurrentFileName)
                {
                    tv.Nodes.Remove(tn);
                    _openedFiles.Remove(uifile.ipdFile.FileName);
                    break;
                }
            }

            ClearLV();
            CurrentFileName = null;
            if (_openedFiles.Count > 0)
            {
                IPDUIFile file = tv.Nodes[0].Tag as IPDUIFile;
                if (file != null)
                    CurrentFileName = file.ipdFile.FileName;
            }   
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if(CurrentFileName != null)
                _openedFiles[CurrentFileName].ipdFile.Save();
        }

        private void mnuEditAsAsciiString_Click(object sender, EventArgs e)
        {
            if ((lv.SelectedItems.Count > 0) && lv.SelectedItems[0].Tag is IPDUIField)
            {
                IPDUIField uiField = (IPDUIField)lv.SelectedItems[0].Tag;
                EditorField efield = new EditorField(lv.SelectedItems[0].Index, uiField.field.type);
                efield.editorName = "IPDEditor.AsciiStringEditor";
                _editors.GetEditorForDatabase(uiField.field.Parent.Parent.name).Add(efield);
            }
        }

        private void importToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (DialogResult.OK == ofd.ShowDialog(this))
            {
                if(CurrentFileName != null)
                    _openedFiles[CurrentFileName].ipdFile.Import(ofd.FileName);
            }
        }

        private void saveAsBin_Click(object sender, EventArgs e)
        {
            if (DialogResult.OK == sfd.ShowDialog(this))
            {
                if (lv.SelectedItems.Count > 0 && lv.SelectedItems[0].Tag is IPDUIField)
                {
                    IPDUIField uiField = (IPDUIField)lv.SelectedItems[0].Tag;
                    FileStream fs = new FileStream(sfd.FileName, FileMode.CreateNew);
                    BinaryWriter bw = new BinaryWriter(fs);
                    bw.Write(uiField.field.data);
                }
                
            }
        }

        private void tv_MouseClick(object sender, MouseEventArgs e)
        {
            if (MouseButtons.Right != e.Button)
            {
                return;
            }
            if (tv.SelectedNode.Tag is IPDVisualRecord)
            {
                this.tvCms.Show(Cursor.Position.X,Cursor.Position.Y);
            }
            
        }

        private void SaveDatabase(IPDDatabase db)
        {
            if (db == null)
            {
                return;
            }

            //assemble all the data of a database
            if (DialogResult.OK == sfd.ShowDialog(this))
            {
                FileStream ms = new FileStream(sfd.FileName,FileMode.CreateNew,FileAccess.ReadWrite);
                BinaryWriter bw = new BinaryWriter(ms);
                db.Write(bw, !db.IsUnicode);
                //byte[] buff = new byte[ms.Length];
                //ms.Seek(0L, SeekOrigin.Begin);
                //ms.Read(buff, 0, (int)ms.Length);
                //rt1.Text = EncUtil.Bin2RichFormat(buff, db.offset);
                bw.Close();
                ms.Close();

            }
        }

        private void saveAsToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            if (tv.SelectedNode.Tag is IPDVisualRecord)
            {
                IPDVisualRecord rec = (IPDVisualRecord)tv.SelectedNode.Tag;

                SaveDatabase(rec.record);

            }
        }


    }
}